package com.seeyon.apps.brwh.manager.impl;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.seeyon.apps.brwh.abstraction.MultipartFileUtils;
import com.seeyon.apps.brwh.cn.hz.comm.EsignHttpHelper;
import com.seeyon.apps.brwh.cn.hz.comm.EsignHttpResponse;
import com.seeyon.apps.brwh.cn.hz.enums.EsignHeaderConstant;
import com.seeyon.apps.brwh.cn.hz.enums.EsignRequestType;
import com.seeyon.apps.brwh.cn.hz.exception.EsignDemoException;
import com.seeyon.apps.brwh.entity.CopierOrgInfo;
import com.seeyon.apps.brwh.entity.CopierPsnInfo;
import com.seeyon.apps.brwh.entity.Copiers;
import com.seeyon.apps.brwh.entity.DocsMsgEntity;
import com.seeyon.apps.brwh.entity.FileMsgEntity;
import com.seeyon.apps.brwh.entity.InitiateRescissionEntity;
import com.seeyon.apps.brwh.entity.MergeFiles;
import com.seeyon.apps.brwh.entity.NormalSignFieldConfigEntity;
import com.seeyon.apps.brwh.entity.NoticeConfigEntity;
import com.seeyon.apps.brwh.entity.OrgInfoEntity;
import com.seeyon.apps.brwh.entity.OrgInitiator;
import com.seeyon.apps.brwh.entity.OrgSignerInfoEntity;
import com.seeyon.apps.brwh.entity.PsnInfoEntity;
import com.seeyon.apps.brwh.entity.RedirectConfigEntity;
import com.seeyon.apps.brwh.entity.RescissionInitiatorEntity;
import com.seeyon.apps.brwh.entity.SealSubEntity;
import com.seeyon.apps.brwh.entity.SignConfigEntity;
import com.seeyon.apps.brwh.entity.SignFieldPositionEntity;
import com.seeyon.apps.brwh.entity.SignFieldsEntity;
import com.seeyon.apps.brwh.entity.SignFlowConfigEntity;
import com.seeyon.apps.brwh.entity.SignFlowConfigsEntity;
import com.seeyon.apps.brwh.entity.SignFlowInitiator;
import com.seeyon.apps.brwh.entity.SignersEntity;
import com.seeyon.apps.brwh.entity.Transactor;
import com.seeyon.apps.brwh.entity.TransactorInfoEntity;
import com.seeyon.apps.brwh.manager.SealManager;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.log.CtpLogFactory;

/**
 * @author zgh
 * @version 1.0 Create by 2024/6/5 15:55
 */
public class SealManagerImpl implements SealManager {


    private Log LOGGER = CtpLogFactory.getLog(SealManagerImpl.class);

    /* 从系统属性中获取配置信息 */
    private final static String eSignHost = AppContext.getSystemProperty("brwh.eqbdyym");


    /**
     * 基于页面签署
     *
     * @param eSignAppId
     * @param eSignAppSecret
     * @return
     * @throws EsignDemoException
     */
    @Override
    public EsignHttpResponse sealPdfByHtml(String eSignAppId, String eSignAppSecret) throws EsignDemoException {
        String apiaddr = "/v3/sign-flow/sign-flow-initiate-url/by-file";
        String jsonParm = "{\n" + "    \"initiatePageConfig\": {\n" + "        \"customBizNum\": \"" + UUID.randomUUID() + "\",\n"
                + "        \"redirectUrl\": \"https://xxx.cn\",\n" + "        \"uneditableFields\": [\n" + "            \"signFlowTitle\",\n"
                + "            \"signFlowExpireTime\",\n" + "            \"copiers\",\n" + "            \"attachments\"\n" + "        ]\n" + "    },\n"
                + "    \"signFlowConfig\": {\n" + "        \"signFlowTitle\": \"合同\",\n" + "        \"autoFinish\": true,\n" + "        \"noticeConfig\": {\n"
                + "            \"noticeTypes\": \"1\"\n" + "        },\n" + "        \"redirectConfig\": {\n" + "            \"redirectUrl\": \"https://baidu.com/\"\n"
                + "        },\n" + "        \"notifyUrl\": \"http://xx.xx.xx.xx:8081/notify\"\n" + "    }\n" + "}";

        //请求方法
        EsignRequestType requestType = EsignRequestType.POST;
        //生成请求签名鉴权方式的Header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }

    /**
     * 基于文件签署
     *
     * @param allFileMsg
     * @return 签署后文件相关信息
     * @throws EsignDemoException
     * @throws InterruptedException
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    @Override
    public Map<String, Object> sealPdfByFile(List<FileMsgEntity> allFileMsg)
            throws EsignDemoException, InterruptedException, IOException, NoSuchAlgorithmException {
        //主文件名称
        String mainSealFileName = null;
        //主文件id
        String mainSealFileId = null;
        //获取一个文件中的属性值作为常量使用
        FileMsgEntity fileMsg = allFileMsg.get(0);
        //新文件 集合
        List<FileMsgEntity> allNewFileMsg = new ArrayList<>();
        //多文件合并文件id
        List<String> fileIds=new ArrayList<>();
        //返回值
        Map<String, Object> map = new HashMap<>();
        //认证信息
        EsignHttpResponse selectIdentityInfo = selectIdentityInfo(fileMsg.getStartSealOrgName(), fileMsg.geteSignAppId(), fileMsg.geteSignAppSecret());
        JSONObject selectIdentityInfoJsonObj = JSONObject.parseObject(selectIdentityInfo.getBody());
        if (selectIdentityInfoJsonObj.getIntValue("code") != 0) {
            map.put("status", 500);
            map.put("msg", selectIdentityInfoJsonObj.getString("message"));
            return map;
        }
        String orgId = selectIdentityInfoJsonObj.getJSONObject("data").getString("orgId");
        LOGGER.info("第一个机构id："+orgId);

//    EsignHttpResponse selectSecondIdentityInfo = selectIdentityInfo(fileMsg.getOrgName(), fileMsg.geteSignAppId(), fileMsg.geteSignAppSecret());
//    JSONObject selectSecondIdentityInfoJsonObj = JSONObject.parseObject(selectSecondIdentityInfo.getBody());
//    if (selectSecondIdentityInfoJsonObj.getIntValue("code") != 0) {
//      map.put("status", 500);
//      map.put("msg", selectSecondIdentityInfoJsonObj.getString("message"));
//      return map;
//    }
//    String orgIdSecond = selectSecondIdentityInfoJsonObj.getJSONObject("data").getString("orgId");
//    LOGGER.info("第二个机构id："+orgIdSecond);
        EsignHttpResponse selectPersonInfo = selectPersonInfo(fileMsg.getStartSealPhone(), fileMsg.geteSignAppId(), fileMsg.geteSignAppSecret());
        JSONObject selectPersonInfoJsonObj = JSONObject.parseObject(selectPersonInfo.getBody());
        if (selectPersonInfoJsonObj.getIntValue("code") != 0) {
            map.put("status", 500);
            map.put("msg", selectPersonInfoJsonObj.getString("message"));
            return map;
        }
        String psnId = selectPersonInfoJsonObj.getJSONObject("data").getString("psnId");
        LOGGER.info("第一个个人id："+psnId);
//    EsignHttpResponse selectSecondPersonInfo = selectPersonInfo(fileMsg.getPsnAccount(), fileMsg.geteSignAppId(), fileMsg.geteSignAppSecret());
//    JSONObject selectSecondPersonInfoJsonObj = JSONObject.parseObject(selectSecondPersonInfo.getBody());
//    if (selectSecondPersonInfoJsonObj.getIntValue("code") != 0) {
//      map.put("status", 500);
//      map.put("msg", selectSecondPersonInfoJsonObj.getString("message"));
//      return map;
//    }
//    String secondPsnId = selectSecondPersonInfoJsonObj.getJSONObject("data").getString("psnId");
//    LOGGER.info("第二个个人id："+secondPsnId);
        for (FileMsgEntity fileMsgEntity : allFileMsg) {
            //获取文件id以及文件上传地址
            EsignHttpResponse getUploadUrl = getUploadUrl(fileMsgEntity.getFileName(), fileMsgEntity.getFilePath(), fileMsgEntity.geteSignAppId(),
                    fileMsgEntity.geteSignAppSecret());
            JSONObject getUploadUrlJsonObject = JSONObject.parseObject(getUploadUrl.getBody());
            JSONObject data = getUploadUrlJsonObject.getJSONObject("data");
            if (getUploadUrlJsonObject.getIntValue("code") != 0) {
                map.put("status", 500);
                map.put("msg", getUploadUrlJsonObject.getString("message"));
                return map;
            }
            //文件id后续发起签署使用
            String fileId = data.get("fileId").toString();
            String fileUploadUrl = data.get("fileUploadUrl").toString();
            LOGGER.info("获取文件id以及文件上传地址成功，文件id:" + fileId);
            LOGGER.info("上传链接:" + fileUploadUrl);
            //文件上传
            EsignHttpResponse uploadFileResponse = uploadFile(fileUploadUrl, fileMsgEntity.getFilePath());
            JSONObject uploadFileResponseJsonObject = JSONObject.parseObject(uploadFileResponse.getBody());
            int errCode = Integer.parseInt(uploadFileResponseJsonObject.get("errCode").toString());
            //0正常 其他非正常
            LOGGER.info("文件上传成功，状态码:" + errCode);
            if (errCode != 0) {
                map.put("status", 500);
                map.put("msg", uploadFileResponseJsonObject.getString("message"));
                return map;
            }
            if (fileMsgEntity.getFileType().equals("1")) {
                int lastDotIndex = fileMsgEntity.getFileName().lastIndexOf('.');
                mainSealFileName = fileMsgEntity.getFileName().substring(0, lastDotIndex);
                mainSealFileId = fileId;
            }
            fileMsgEntity.setFileId(fileId);
            fileIds.add(fileId);
        }
        Thread.sleep(2000);
        //文件合并
        if (fileIds.size()>1) {
            EsignHttpResponse mergeFilesHttpResponse = mergeFiles(mainSealFileName, fileIds, fileMsg.geteSignAppId(), fileMsg.geteSignAppSecret());
            JSONObject mergeFilesJsonObject = JSONObject.parseObject(mergeFilesHttpResponse.getBody());
            if (mergeFilesJsonObject.getIntValue("code") != 0) {
                map.put("status", 500);
                map.put("msg", mergeFilesJsonObject.getString("message"));
                return map;
            }
            mainSealFileId = mergeFilesJsonObject.getJSONObject("data").getString("mergedFileId");

        }
        Thread.sleep(2000);
        fileMsg.setFileId(mainSealFileId);
        fileMsg.setFileName(mainSealFileName);
        allNewFileMsg.add(fileMsg);

        //发起签署
        EsignHttpResponse createByFile = createByFile(allNewFileMsg, orgId, psnId,fileMsg.getOrgName(),fileMsg.getPsnAccount() ,mainSealFileName, mainSealFileId);
        LOGGER.info("发起签署返回" + JSON.toJSONString(createByFile));
        JSONObject createByFileJsonObject = JSONObject.parseObject(createByFile.getBody());
        String signFlowId = null;
        if (createByFileJsonObject.getIntValue("code") == 0) {
            signFlowId = createByFileJsonObject.getJSONObject("data").getString("signFlowId");
            LOGGER.info("signFlowId:" + signFlowId);
        } else {
            map.put("status", 500);
            map.put("msg", createByFileJsonObject.getString("message"));
            return map;
        }
        //获取合同文件预览链接
        EsignHttpResponse esignHttpResponse = signUrl(signFlowId, fileMsg.geteSignAppId(), fileMsg.geteSignAppSecret(), fileMsg.getStartSealOrgName().trim(), 1,
                fileMsg.getStartSealPhone());
        JSONObject signUrlJson = JSONObject.parseObject(esignHttpResponse.getBody());
        if (signUrlJson.getIntValue("code") != 0) {
            map.put("msg", signUrlJson.getString("message"));
            map.put("status", 500);
            return map;
        }
        String url = signUrlJson.getJSONObject("data").getString("url");
        LOGGER.info("-----------------------lookUrl=-------------------------" + url);

        //获取合同文件签署链接
        EsignHttpResponse writeEsignHttpResponse = signUrl(signFlowId, fileMsg.geteSignAppId(), fileMsg.geteSignAppSecret(), fileMsg.getStartSealOrgName().trim(),
                2, fileMsg.getStartSealPhone());
        JSONObject writeSignUrlJson = JSONObject.parseObject(writeEsignHttpResponse.getBody());
        if (writeSignUrlJson.getIntValue("code") != 0) {
            map.put("msg", writeSignUrlJson.getString("message"));
            map.put("status", 500);
            return map;
        }
        String writeUrl = writeSignUrlJson.getJSONObject("data").getString("url");
        LOGGER.info("-----------------------writeUrl=-------------------------" + writeUrl);

        map.put("msg", "发起成功,点击合同预览查看效果");
        map.put("status", 200);
        map.put("fileId", mainSealFileId);
        map.put("signFlowId", signFlowId);
        map.put("lookUrl", url);
        map.put("writeUrl", writeUrl);
        return map;
    }


    /**
     * 下载
     *
     * @param map
     * @return
     * @throws EsignDemoException
     */
    @Override
    public EsignHttpResponse downLoadSealPdf(Map<String, Object> map) throws EsignDemoException {
        //下载已签署文件及附属材料
        EsignHttpResponse esignHttpResponse = fileDownloadUrl(map.get("signFlowId").toString(), map.get("eSignAppId").toString(),
                map.get("eSignAppSecret").toString());
        LOGGER.info(JSONObject.toJSONString(esignHttpResponse));
        return esignHttpResponse;
    }

    /**
     * 合同作废
     *
     * @param signFlowId 流程id
     * @return
     */
    @Override
    public Map<String, Object> delSealPdf(String signFlowId, String eSignAppId, String eSignAppSecret, List<String> fileId, String certifyID, String firstOrgName,
                                          String firstPsnAccount, String secondOrgName, String secondPsnAccount, String reason, String reasonMsg) throws EsignDemoException {
        Map<String, Object> map = new HashMap<>();
        if(signFlowId==null||StringUtils.isBlank(signFlowId)){
            map.put("status", "500");
            map.put("msg", "合同流程ID为空,请先进行合同签署！");
            return map;
        }
        EsignHttpResponse esignHttpResponse = selectDetail(signFlowId, eSignAppId, eSignAppSecret);
        JSONObject selectKeyWords = JSONObject.parseObject(esignHttpResponse.getBody());
        JSONObject keyWordPxs = selectKeyWords.getJSONObject("data");
        int signFlowStatus = keyWordPxs.getIntValue("signFlowStatus");
        EsignHttpResponse esignHttpResponse1 = null;
        if (signFlowStatus != 2) {
            //合同在未签署或者单方签署中解约
            esignHttpResponse1 = revokeSealPdf(signFlowId, eSignAppId, eSignAppSecret, reasonMsg);
            JSONObject revokeRes = JSONObject.parseObject(esignHttpResponse1.getBody());
            if (revokeRes.getIntValue("code") != 0) {
                map.put("status", "500");
                map.put("msg", revokeRes.getString("message"));
                return map;
            }
            map.put("status", "200");
            map.put("msg", "解约成功！");
            return map;
        }
        //认证结果查询
        if (certifyID == null || certifyID.equals("")) {
            map.put("status", 500);
            map.put("msg", "请先点击认证授权！");
            return map;
        }
        esignHttpResponse1 = authFlow(certifyID, eSignAppId, eSignAppSecret);

        JSONObject revokeRes = JSONObject.parseObject(esignHttpResponse1.getBody());
        if (revokeRes.getIntValue("code") != 0) {
            map.put("status", "500");
            map.put("msg", revokeRes.getString("message"));
            return map;
        }
        JSONObject revokeResMsg = revokeRes.getJSONObject("data");
        JSONObject authInfo = revokeResMsg.getJSONObject("authInfo");
        JSONObject person = authInfo.getJSONObject("person");
        //获取人员id
        String psnId = person.getString("psnId");
        JSONObject organization = authInfo.getJSONObject("organization");
        //获取企业id
        String orgId = organization.getString("orgId");
        //发起解约
        EsignHttpResponse rescission = rescission(eSignAppId, eSignAppSecret, fileId, signFlowId, orgId, psnId, reason, reasonMsg);
        JSONObject rescissionRes = JSONObject.parseObject(rescission.getBody());
        if (rescissionRes.getIntValue("code") != 0) {
            map.put("status", "500");
            map.put("msg", rescissionRes.getString("message"));
            return map;
        }
        JSONObject rescissionResMsg = rescissionRes.getJSONObject("data");
        //解约流程id
        String rescissionSignFlowId = rescissionResMsg.getString("signFlowId");
        //甲方
        EsignHttpResponse firstRes = signUrl(rescissionSignFlowId, eSignAppId, eSignAppSecret, firstOrgName, 2, firstPsnAccount);
        JSONObject rescissionFirstRes = JSONObject.parseObject(firstRes.getBody());
        if (rescissionFirstRes.getIntValue("code") != 0) {
            map.put("status", "500");
            map.put("msg", rescissionFirstRes.getString("message"));
            return map;
        }
        //乙方
        EsignHttpResponse secondRes = signUrl(rescissionSignFlowId, eSignAppId, eSignAppSecret, secondOrgName, 2, secondPsnAccount);
        JSONObject rescissionSecondRes = JSONObject.parseObject(secondRes.getBody());
        if (rescissionSecondRes.getIntValue("code") != 0) {
            map.put("status", "500");
            map.put("msg", rescissionSecondRes.getString("message"));
            return map;
        }
        JSONObject rescissionFirstResMsg = rescissionFirstRes.getJSONObject("data");
        String url = rescissionFirstResMsg.getString("url");
        map.put("status", "200");
        map.put("msg", "请进行解约合同签署！");
        map.put("url", url);
        return map;
    }

    /**
     * 认证
     *
     * @throws EsignDemoException
     */
    @Override
    public Map<String, Object> sealCertify(String appId, String appSercert, String orgName, String phone) throws EsignDemoException {
        EsignHttpResponse esignHttpResponse = orgAuthUrl(orgName, phone, appId, appSercert);
        JSONObject res = JSONObject.parseObject(esignHttpResponse.getBody());
        JSONObject resObj = res.getJSONObject("data");
        HashMap<String, Object> resMap = new HashMap<>();
        if (res.getIntValue("code") != 0) {
            resMap.put("status", 500);
            resMap.put("msg", res.getString("message"));
            return resMap;
        }
        resMap.put("status", 200);
        resMap.put("msg", "授权完成后,可进行下步操作");
        resMap.put("authShortUrl", resObj.getString("authShortUrl"));
        resMap.put("authFlowId", resObj.getString("authFlowId"));
        return resMap;
    }

    /**
     * 发起合同解约
     *
     * @return
     */
    public static EsignHttpResponse rescission(String eSignAppId, String eSignAppSecret, List<String> fileId, String signFlowId, String orgId, String psnId,
                                               String reason, String reasonMsg) throws EsignDemoException {
        String apiaddr = "/v3/sign-flow/" + signFlowId + "/initiate-rescission";
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        InitiateRescissionEntity rescissionEntity = new InitiateRescissionEntity(fileId, reason, reasonMsg,
                new RescissionInitiatorEntity(new OrgInitiator(orgId, new Transactor(psnId))), new SignFlowConfigsEntity(new NoticeConfigEntity("1")));
        String jsonParm = JSON.toJSONString(rescissionEntity);
        //请求方法
        EsignRequestType requestType = EsignRequestType.POST;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }

    /**
     * 查询认证授权流程详情
     *
     * @return
     */
    public static EsignHttpResponse authFlow(String certifyID, String eSignAppId, String eSignAppSecret) throws EsignDemoException {
        String apiaddr = "/v3/auth-flow/" + certifyID;
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        String jsonParm = null;
        //请求方法
        EsignRequestType requestType = EsignRequestType.GET;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }

    /**
     * 获取机构认证&授权页面链接
     *
     * @return
     */
    public static EsignHttpResponse orgAuthUrl(String orgName, String phone, String eSignAppId, String eSignAppSecret) throws EsignDemoException {
        String apiaddr = "/v3/org-auth-url";
        String jsonParm = "{\n" + "    \"orgAuthConfig\": {\n" + "        \"orgName\": \"" + orgName + "\",\n" + "        \"transactorInfo\": {\n"
                + "            \"psnAccount\": \"" + phone + "\"\n" + "        }\n" + "    },\n" + "    \"authorizeConfig\": {\n" + "        \"authorizedScopes\": [\n"
                + "            \"org_initiate_sign\",\n" + "            \"psn_initiate_sign\"\n" + "        ]\n" + "    }\n" + "}";
        //请求方法
        EsignRequestType requestType = EsignRequestType.POST;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }

    /**
     * 查询机构认证信息
     *
     * @return
     */
    public static EsignHttpResponse selectIdentityInfo(String orgName, String eSignAppId, String eSignAppSecret) throws EsignDemoException {
        String apiaddr = "/v3/organizations/identity-info?orgName=" + orgName;
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        String jsonParm = null;
        //请求方法
        EsignRequestType requestType = EsignRequestType.GET;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }

    /**
     * 查询个人认证信息
     *
     * @return
     */
    public static EsignHttpResponse selectPersonInfo(String phone, String eSignAppId, String eSignAppSecret) throws EsignDemoException {
        String apiaddr = "/v3/persons/identity-info?psnAccount=" + phone;
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        String jsonParm = null;
        //请求方法
        EsignRequestType requestType = EsignRequestType.GET;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }


    /**
     * 查询签署流程详情
     *
     * @return
     */
    public static EsignHttpResponse selectDetail(String signFlowId, String eSignAppId, String eSignAppSecret) throws EsignDemoException {
        String apiaddr = "/v3/sign-flow/" + signFlowId + "/detail";
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        String jsonParm = null;
        //请求方法
        EsignRequestType requestType = EsignRequestType.GET;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }


    /**
     * 撤销签署流程
     *
     * @return
     */
    public static EsignHttpResponse revokeSealPdf(String signFlowId, String eSignAppId, String eSignAppSecret, String msg) throws EsignDemoException {
        String apiaddr = "/v3/sign-flow/" + signFlowId + "/revoke";
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        String jsonParm = "{\n" + "    \"revokeReason\": \"" + msg + "\"\n" + "}";
        //请求方法
        EsignRequestType requestType = EsignRequestType.POST;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }

    /**
     * 基于文件发起签署 mainSealFileId 主合同id mainSealFileName 主合同名称
     *
     * @return
     * @throws EsignDemoException
     */
    public EsignHttpResponse createByFile(List<FileMsgEntity> fileMsg, String orgId, String psnId,String  orgName,String psnAccount, String mainSealFileName, String mainSealFileId)
            throws EsignDemoException {
        String apiaddr = "/v3/sign-flow/create-by-file";
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        SealSubEntity sealSub = new SealSubEntity();
        List<Copiers> copiersList=new ArrayList<>();
        Copiers copiers = new Copiers();
        copiers.setCopierOrgInfo(new CopierOrgInfo(orgName));
        copiers.setCopierPsnInfo(new CopierPsnInfo(psnAccount));
        copiersList.add(copiers);
        sealSub.setCopiers(copiersList);
        OrgInitiator orgInitiator = new OrgInitiator();
        orgInitiator.setOrgId(orgId);
        orgInitiator.setTransactor(new Transactor(psnId));
        sealSub.setSignFlowInitiator(new SignFlowInitiator(orgInitiator));
        List<DocsMsgEntity> list = new ArrayList<>();
        for (FileMsgEntity fileOnceMsg : fileMsg) {
            list.add(new DocsMsgEntity(fileOnceMsg.getFileId(), fileOnceMsg.getFileName()));
        }
        //文件名称和id
        sealSub.setDocs(list);
        //合同相关配置                                                  "http://"+fileMsg.getIpConfig()+"/seeyon/rest/jssdk/notifiySealPdf"
        sealSub.setSignFlowConfig(new SignFlowConfigEntity(mainSealFileName, true, "", new RedirectConfigEntity(""), new NoticeConfigEntity("1,2")));
        //调用查找关键字
        Map<String, JSONObject> selectKeyWordMap = new HashMap<>();
        //原所有文件均盖章修改为主文件盖章
        //    for (FileMsgEntity fileOnceMsg : fileMsg) {
        //      EsignHttpResponse selectKeyWord = selectKeyWord(fileOnceMsg.getFileId(), fileOnceMsg.geteSignAppId(), fileOnceMsg.geteSignAppSecret(),
        //          fileOnceMsg.getASealLocation(), fileOnceMsg.getBsealLocation(), "");
        EsignHttpResponse selectKeyWord = selectKeyWord(mainSealFileId, fileMsg.get(0).geteSignAppId(), fileMsg.get(0).geteSignAppSecret(),
                fileMsg.get(0).getASealLocation(), fileMsg.get(0).getBsealLocation(), "");
        JSONObject selectKeyWords = JSONObject.parseObject(selectKeyWord.getBody());
        JSONObject keyWordPxs = selectKeyWords.getJSONObject("data");
        selectKeyWordMap.put(mainSealFileId, keyWordPxs);
        //    }
        //用户信息
        List<SignersEntity> signer = new ArrayList<>();
        //甲方
        SignersEntity firstSigners = new SignersEntity();
        firstSigners.setSignerType(1);
        firstSigners.setSignConfig(new SignConfigEntity(2, 10));
        OrgSignerInfoEntity startOrgSignerInfo = new OrgSignerInfoEntity();
        startOrgSignerInfo.setOrgName(fileMsg.get(0).getStartSealOrgName());
        startOrgSignerInfo.setOrgInfo(new OrgInfoEntity(fileMsg.get(0).getStartSealOrgIdCard(), "CRED_ORG_USCC"));
        TransactorInfoEntity startTransactorInfo = new TransactorInfoEntity();
        startTransactorInfo.setPsnAccount(fileMsg.get(0).getStartSealPhone());
        startTransactorInfo.setPsnInfo(new PsnInfoEntity(fileMsg.get(0).getStartSealName()));
        startOrgSignerInfo.setTransactorInfo(startTransactorInfo);
        firstSigners.setOrgSignerInfo(startOrgSignerInfo);
        //乙方
        SignersEntity secondSigners = new SignersEntity();
        secondSigners.setSignerType(1);
        secondSigners.setSignConfig(new SignConfigEntity(1, 10));
        OrgSignerInfoEntity orgSignerInfo = new OrgSignerInfoEntity();
        orgSignerInfo.setOrgName(fileMsg.get(0).getOrgName());
        orgSignerInfo.setOrgInfo(new OrgInfoEntity(fileMsg.get(0).getOrgIDCardNum(), "CRED_ORG_USCC"));
        TransactorInfoEntity transactorInfo = new TransactorInfoEntity();
        transactorInfo.setPsnAccount(fileMsg.get(0).getPsnAccount());
        transactorInfo.setPsnInfo(new PsnInfoEntity(fileMsg.get(0).getPsnName()));
        orgSignerInfo.setTransactorInfo(transactorInfo);
        secondSigners.setOrgSignerInfo(orgSignerInfo);
        //甲方印章配置
        List<SignFieldsEntity> firstSignFields = new ArrayList<>();
        //甲方骑缝章
        for (FileMsgEntity fileOnceMsg : fileMsg) {
            SignFieldsEntity perForSignFields = new SignFieldsEntity();
            perForSignFields.setFileId(fileOnceMsg.getFileId());
            perForSignFields.setCustomBizNum(UUID.randomUUID().toString());
            //设置Y轴位置
            SignFieldPositionEntity signFieldPosition = new SignFieldPositionEntity();
            signFieldPosition.setPositionY(200.0);
            //设置印章类型,是否自动盖章  1盖章2骑缝章
            NormalSignFieldConfigEntity normalSignFieldConfig = new NormalSignFieldConfigEntity();
            normalSignFieldConfig.setSignFieldStyle(2);
            normalSignFieldConfig.setAutoSign(false);
            normalSignFieldConfig.setSignFieldPosition(signFieldPosition);
            perForSignFields.setNormalSignFieldConfig(normalSignFieldConfig);
            firstSignFields.add(perForSignFields);
        }
        //乙方印章配置
        List<SignFieldsEntity> secondSignFields = new ArrayList<>();
        //乙方骑缝章
        for (FileMsgEntity fileOnceMsg : fileMsg) {
            SignFieldsEntity perForSeSignFields = new SignFieldsEntity();
            perForSeSignFields.setFileId(fileOnceMsg.getFileId());
            perForSeSignFields.setCustomBizNum(UUID.randomUUID().toString());
            //设置Y轴位置
            SignFieldPositionEntity signSeFieldPosition = new SignFieldPositionEntity();
            signSeFieldPosition.setPositionY(400.0);
            //设置印章类型,是否自动盖章  1盖章2骑缝章
            NormalSignFieldConfigEntity normalSeSignFieldConfig = new NormalSignFieldConfigEntity();
            normalSeSignFieldConfig.setSignFieldStyle(2);
            normalSeSignFieldConfig.setAutoSign(false);
            normalSeSignFieldConfig.setSignFieldPosition(signSeFieldPosition);
            perForSeSignFields.setNormalSignFieldConfig(normalSeSignFieldConfig);
            secondSignFields.add(perForSeSignFields);
        }
        //key是fileId
        for (String key : selectKeyWordMap.keySet()) {
            JSONArray keywordPositions = selectKeyWordMap.get(key).getJSONArray("keywordPositions");
            List<Map<String, Object>> parse = (List<Map<String, Object>>) JSON.parse(keywordPositions.toString());
            LOGGER.info("查找关键字:" + parse);
            for (Map<String, Object> stringObjectMap : parse) {
                String keyword = stringObjectMap.get("keyword").toString();
                if (StringUtils.containsIgnoreCase(keyword, "甲方")) {
                    List<SignFieldsEntity> signFields1 = coordinatePlane(stringObjectMap.get("positions"), key, keyword);
                    firstSignFields.addAll(signFields1);
                } else {
                    List<SignFieldsEntity> signFields2 = coordinatePlane(stringObjectMap.get("positions"), key, keyword);
                    secondSignFields.addAll(signFields2);
                }
            }
        }
        firstSigners.setSignFields(firstSignFields);
        signer.add(firstSigners);
        secondSigners.setSignFields(secondSignFields);
        signer.add(secondSigners);
        sealSub.setSigners(signer);
        //实体类转json
        String jsonParm = JSON.toJSONString(sealSub);
        LOGGER.info("请求参数值：" + jsonParm);
        //请求方法
        EsignRequestType requestType = EsignRequestType.POST;
        //生成请求签名鉴权方式的Header
        Map<String, String> header = EsignHttpHelper
                .signAndBuildSignAndJsonHeader(fileMsg.get(0).geteSignAppId(), fileMsg.get(0).geteSignAppSecret(), jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }

    /**
     * 查找关键字
     *
     * @param fileId
     * @param eSignAppId
     * @param eSignAppSecret
     * @return
     * @throws EsignDemoException
     */
    public static EsignHttpResponse selectKeyWord(String fileId, String eSignAppId, String eSignAppSecret, String ASealLocation, String BSealLocation,
                                                  String wordLocation) throws EsignDemoException {
        String apiaddr = "/v3/files/" + fileId + "/keyword-positions";
        String jsonParm = null;
        if (StringUtils.isEmpty(wordLocation)) {
            jsonParm = "{\n" + "  \"keywords\": [\n" + "    \"" + ASealLocation + "\",\n" + "    \"" + BSealLocation + "\"\n" + "  ]\n" + "}";
        } else {
            jsonParm =
                    "{\n" + "  \"keywords\": [\n" + "    \"" + ASealLocation + "\",\n" + "    \"" + BSealLocation + "\"\n" + "    \"" + wordLocation + "\"\n" + "  ]\n"
                            + "}";
        }
        EsignRequestType requestType = EsignRequestType.POST;
        //生成请求签名鉴权方式的Header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }


    /**
     * 坐标值解析
     *
     * @param positions
     */
    public List<SignFieldsEntity> coordinatePlane(Object positions, String field, String keyWord) {
        List<SignFieldsEntity> signFieldsList = new ArrayList<>();
        List<Map<String, Object>> s = (List<Map<String, Object>>) positions;
        for (Map<String, Object> objectMap : s) {
            List<Map<String, Object>> s2 = (List<Map<String, Object>>) objectMap.get("coordinates");
            for (Map<String, Object> map : s2) {
                SignFieldsEntity signFields = new SignFieldsEntity();
                signFields.setFileId(field);
                NormalSignFieldConfigEntity normalSignFieldConfig = new NormalSignFieldConfigEntity();
                normalSignFieldConfig.setSignFieldStyle(1);
                normalSignFieldConfig.setAutoSign(false);
                signFields.setCustomBizNum(UUID.randomUUID().toString());
                SignFieldPositionEntity signFieldPosition = new SignFieldPositionEntity();
                signFieldPosition.setPositionPage(objectMap.get("pageNum").toString());
                signFieldPosition.setPositionX(Double.parseDouble(map.get("positionX").toString()) + 126);
                signFieldPosition.setPositionY(Double.parseDouble(map.get("positionY").toString()) - 41);
                normalSignFieldConfig.setSignFieldPosition(signFieldPosition);
                signFields.setNormalSignFieldConfig(normalSignFieldConfig);
                signFieldsList.add(signFields);
            }
        }
        return signFieldsList;
    }

    /**
     * 下载已签署文件及附属材料
     *
     * @return
     * @throws EsignDemoException
     */
    public static EsignHttpResponse fileDownloadUrl(String signFlowId, String eSignAppId, String eSignAppSecret) throws EsignDemoException {
        String apiaddr = "/v3/sign-flow/" + signFlowId + "/file-download-url";
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        String jsonParm = null;
        //请求方法
        EsignRequestType requestType = EsignRequestType.GET;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }

    /**
     * 查询文件上传状态
     *
     * @return
     * @throws EsignDemoException
     */
    public static EsignHttpResponse fileStatus(String fileId, String eSignAppId, String eSignAppSecret) throws EsignDemoException {
        String apiaddr = "/v3/files/" + fileId;
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        String jsonParm = null;
        //请求方法
        EsignRequestType requestType = EsignRequestType.GET;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }


    /**
     * 多文件合并
     * @param fileName 合并后文件名称
     * @param fileIds 合并文件id
     * @param eSignAppId appid
     * @param eSignAppSecret app密钥
     * @return
     * @throws EsignDemoException
     */
    public static EsignHttpResponse mergeFiles(String fileName, List<String> fileIds, String eSignAppId, String eSignAppSecret) throws EsignDemoException {
        String apiaddr = "/v3/files/merge-files";
        MergeFiles mergeFiles = new MergeFiles(fileName, fileIds);
        String jsonParm = JSON.toJSONString(mergeFiles);
        //请求方法
        EsignRequestType requestType = EsignRequestType.POST;
        //生成请求签名鉴权方式的Header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }

    /**
     * 获取合同文件签署链接
     *
     * @return
     * @throws EsignDemoException
     */
    public static EsignHttpResponse signUrl(String signFlowId, String eSignAppId, String eSignAppSecret, String orgname, Integer urlType, String phone)
            throws EsignDemoException {
        String apiaddr = "/v3/sign-flow/" + signFlowId + "/sign-url";
        String jsonParm =
                "{\n" + "    \"clientType\": \"ALL\",\n" + "    \"needLogin\": false,\n" + "    \"operator\": {\n" + "        \"psnAccount\": \"" + phone + "\"\n"
                        + "    },\n" + "    \"organization\": {\n" + "        \"orgName\": \"" + orgname + "\"\n" + "    },\n" + "    \"urlType\": " + urlType + "\n" + "}";
        //请求方法
        EsignRequestType requestType = EsignRequestType.POST;
        //生成请求签名鉴权方式的Header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }

    /**
     * 获取文件上传地址
     *
     * @return
     */
    public static EsignHttpResponse getUploadUrl(String fileName, MultipartFile file, String eSignAppId, String eSignAppSecret)
            throws EsignDemoException, IOException, NoSuchAlgorithmException {
        //自定义的文件封装类，传入文件地址可以获取文件的名称大小,文件流等数据
        String apiaddr = "/v3/files/file-upload-url";
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        String jsonParm =
                "{\n" + "    \"contentMd5\": \"" + MultipartFileUtils.calculateMD5(file) + "\",\n" + "    \"fileName\":\"" + fileName + "\"," + "    \"fileSize\": "
                        + file.getSize() + ",\n" + "    \"convertToPDF\": true,\n" + "    \"contentType\": \"" + EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE() + "\"\n"
                        + "}";
        //请求方法
        EsignRequestType requestType = EsignRequestType.POST;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
        //发起接口请求
        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
    }

    /**
     * 文件流上传
     *
     * @return
     */
    public static EsignHttpResponse uploadFile(String uploadUrl, MultipartFile file) throws EsignDemoException, IOException, NoSuchAlgorithmException {
        //请求方法
        EsignRequestType requestType = EsignRequestType.PUT;
        return EsignHttpHelper
                .doUploadHttp(uploadUrl, requestType, file.getBytes(), MultipartFileUtils.calculateMD5(file), EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE(), true);
    }

}
